<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>基础模板文件</title>
  <link href="./static/css/global.css" rel="stylesheet" />
  <link href="./static/css/element-ui2.15.7.min.css" rel="stylesheet" />
</head>
<style stype="text/css">
  .main {
    background-color: #F1F1F1;
  }

  .search-container {
    padding: 20px 20px 0 20px;
    background-color: #fff;
    margin-bottom: 20px;
  }

  .main-container {
    background-color: #fff;
    padding: 20px;
    box-sizing: border-box;
  }

  .wapper-bar {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 18px;
  }

  .table-box {
    margin-bottom: 20px;
  }

  .pagination-box {
    width: 100%;
    display: flex;
    justify-content: flex-end;
  }

  .form-card-item {
    width: 100%;
  }

  .form-card-item-image {
    display: block;
    width: 100%;
  }

  .el-dialog__header {
    border-bottom: 1px solid #F1F1F1;
    padding-bottom: 20px;
  }

  .el-dialog__headerbtn {
    top: 25px;
  }

  .el-upload {
    width: 100%;
  }

  .el-upload-dragger {
    width: 100%;
    height: 400px;
    flex-direction: column;
    display: flex;
    justify-content: center;
    align-items: center;
  }
</style>

<body>
  <div id="app">
    <div v-cloak class="container-box">
      <div class="main">
        <div class="search-container">
          <el-form :inline="true" :model="formInline">
            <el-form-item label="文件名">
              <el-input v-model="formInline.fileName" placeholder="请输入文件名"></el-input>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="el-icon-search" @click="onSearch">查询</el-button>
              <el-button type="info" icon="el-icon-refresh-left" @click="onReset">重置</el-button>
              <el-button type="warning" plain icon="el-icon-switch-button" @click="onLogout">退出登录</el-button>
            </el-form-item>
          </el-form>
        </div>
        <div class="main-container">
          <div class="wapper-bar">
            <div class="wapper-left">
              <div class="wapper-bar-title">文件列表</div>
            </div>
            <div class="wapper-right">
              <el-button type="primary" @click="addModal" icon="el-icon-plus">上传文件</el-button>
              <!-- <el-button type="danger" icon="el-icon-delete">删除</el-button> -->
            </div>
          </div>
          <el-table class="table-box" ref="multipleTable" :data="tableData" tooltip-effect="dark" style="width: 100%"
            height="680" @selection-change="handleSelectionChange">
            <el-table-column type="selection" width="55" align="center">
            </el-table-column>
            <el-table-column prop="fileName" label="文件名" width="260">
            </el-table-column>
            <el-table-column prop="path" label="地址" show-overflow-tooltip>
            </el-table-column>
            <el-table-column prop="size" label="文件大小(kb)" width="200">
            </el-table-column>
            <el-table-column label="操作" align="center" width="180">
              <template slot-scope="scope">
                <el-button type="danger" @click="del(scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
          <div class="pagination-box">
            <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
              :current-page="formInline.pageNum" :page-sizes="pagesizes" :page-size="formInline.pageSize"
              layout="total, sizes, prev, pager, next, jumper" :total="total">
            </el-pagination>
          </div>
        </div>
        <el-dialog title="上传文件" :visible.sync="dialogVisible" width="50%">
          <div>
            <el-upload class="upload-demo" :before-upload="handleBeforeUpload" drag action="#">
              <i class="el-icon-upload"></i>
              <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
              <!-- <div class="el-upload__tip" slot="tip">只能上传jpg/png文件，且不超过500kb</div> -->
            </el-upload>
          </div>
          <span slot="footer" class="dialog-footer">
            <el-button @click="dialogVisible = false">取 消</el-button>
            <!-- <el-button type="primary" @click="submitForm">确 定</el-button> -->
          </span>
        </el-dialog>
      </div>
    </div>
  </div>
</body>
<script src="./static/js/vue2.6.14.min.js"></script>
<script src="./static/js/element-ui2.15.7.min.js"></script>
<script src="./static/js/axios1.2.3.min.js"></script>
<script src="./static/js/qs6.7.0.min.js"></script>
<script src="./static/js/request.js"></script>
<script src="./static/js/spark-md5.min.js"></script>
<script>
  new Vue({
    props: [],
    components: {},
    data() {
      return {
        total: 0,
        pagesizes: [10, 20, 50, 100],
        formInline: {
          pageNum: 1,
          pageSize: 10,
          fileName: "",
        },
        tableData: [],
        multipleSelection: [],
        dialogVisible: false,
        fileSize: 0,
        chunkSize: 5 * 1024 * 1024,
        file: null,
        hasUploaded: 0,
        chunks: 0
      }
    },
    watch: {},
    computed: {},
    beforeCreate() { },
    created() {
      this.getList();
    },
    beforeMount() { },
    mounted() { },
    beforeUpdate() { },
    updated() { },
    destroyed() { },
    methods: {
      // 获取列表
      getList() {
        getFileList(this.formInline).then((res) => {
          if (res.stat == 1) {
            this.tableData = res.rows;
            this.total = res.total
          }
        })
      },
      // 前往表单
      goForm() {
        this.$router.push({
          name: "formEditor",
        });
      },
      // 添加
      add() {
        window.location.href = "./upload.html"
      },
      // 添加
      addModal() {
        this.dialogVisible = true;
      },


      // 上传前处理，返回false改为手动上传
      handleBeforeUpload(file) {
        this.file = file;
        this.fileSize = file.size;
        this.responseChange(file)
        return false;
      },

      // 响应开始上传
      async responseChange(file) {
        // 第一步：按照 修改时间+文件名称+最后修改时间-->MD5
        // 开始校验
        let fileMd5Value = await this.md5File(file)
        console.log('fileMd5Value', fileMd5Value)
        // 第二步：校验文件的MD5
        let result = await this.checkFileMD5(file.name, fileMd5Value)
        // 如果文件已存在, 就秒传
        if (result.file) {
          console.log('文件已秒传')
          this.dialogVisible = false;
          this.fileSize = 0;
          this.chunkSize = 5 * 1024 * 1024;
          this.file = null;
          this.hasUploaded = 0;
          this.chunks = 0;
          this.$message.success('文件已存在');
          this.getList();
          return
        }
        // 第三步：检查并上传MD5
        await this.checkAndUploadChunk(fileMd5Value, result.chunkList)
        // 第四步: 通知服务器所有分片已上传完成
        this.notifyServer(fileMd5Value)
      },

      // 1.修改时间+文件名称+最后修改时间-->MD5
      md5File(file) {
        return new Promise((resolve, reject) => {
          var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
            //chunkSize = 2097152, // Read in chunks of 2MB
            chunkSize = file.size / 100,
            //chunks = Math.ceil(file.size / chunkSize),
            chunks = 100,
            currentChunk = 0,
            spark = new SparkMD5.ArrayBuffer(),
            fileReader = new FileReader();
          fileReader.onload = function (e) {
            console.log('read chunk nr', currentChunk + 1, 'of', chunks);
            spark.append(e.target.result); // Append array buffer
            currentChunk++;

            if (currentChunk < chunks) {
              loadNext();
            } else {
              let cur = +(new Date())
              console.log('finished loading');
              let result = spark.end()
              resolve(result)
            }
          };
          fileReader.onerror = function () {
            console.warn('oops, something went wrong.');
          };
          function loadNext() {
            var start = currentChunk * chunkSize,
              end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
            fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
          }
          loadNext();
        })
      },

      // 2.校验文件的MD5
      checkFileMD5(fileName, fileMd5Value) {
        return new Promise((resolve, reject) => {
          let params = {
            fileName: fileName,
            fileMd5Value: fileMd5Value
          }
          checkFile(params).then((res) => {
            resolve(res)
          })
        })
      },

      // 3.上传chunk
      async checkAndUploadChunk(fileMd5Value, chunkList) {
        this.chunks = Math.ceil(this.fileSize / this.chunkSize)
        this.hasUploaded = chunkList.length
        for (let i = 0; i < this.chunks; i++) {
          let exit = chunkList.indexOf(i + "") > -1
          // 如果已经存在, 则不用再上传当前块
          if (!exit) {
            let index = await this.upload(i, fileMd5Value, this.chunks)
            this.hasUploaded++
            let radio = Math.floor((this.hasUploaded / this.chunks) * 100)
          }
        }
      },

      // 3-2. 上传chunk
      upload(i, fileMd5Value, chunks) {
        return new Promise((resolve, reject) => {
          //构造一个表单，FormData是HTML5新增的
          let end = (i + 1) * this.chunkSize >= this.file.size ? this.file.size : (i + 1) * this.chunkSize
          let form = new FormData()
          form.append("data", this.file.slice(i * this.chunkSize, end)) //file对象的slice方法用于切出文件的一部分
          form.append("total", chunks) //总片数
          form.append("index", i) //当前是第几片     
          form.append("fileMd5Value", fileMd5Value)
          uploadFile(form).then((data) => {
            resolve(data.desc)
          })
        })

      },

      // 第四步: 通知服务器所有分片已上传完成
      notifyServer(fileMd5Value) {
        let params = {
          md5: fileMd5Value,
          fileName: this.file.name,
          size: this.file.size
        }
        merge(params).then((data) => {
          this.dialogVisible = false;
          this.fileSize = 0;
          this.chunkSize = 5 * 1024 * 1024;
          this.file = null;
          this.hasUploaded = 0;
          this.chunks = 0;
          this.$message.success('上传成功');
          this.getList();
          console.log('上传成功')
        })
      },


      // 查询
      onSearch() {
        this.getList();
      },
      // 重置表单
      onReset() {
        this.formInline = {
          pageNum: 1,
          pageSize: 10,
          fileName: "",
        },
          this.getList();
      },
      // 每页条数发生变化回调
      handleSizeChange(size) {
        this.formInline.pageSize = size;
        this.getList();
      },
      // 页码发生变化回调
      handleCurrentChange(page) {
        this.formInline.pageNum = page;
        this.getList();
      },
      // 表格复选回调
      handleSelectionChange(val) {
        this.multipleSelection = val;
      },
      // 删除文件
      del(row) {
        let _this = this;
        let params = {
          path: row.path
        }
        _this.$confirm('您确定要删除选中的数据项吗？', '温馨提示', {
          distinguishCancelAndClose: true,
          confirmButtonText: '确定',
          cancelButtonText: '取消'
        }).then(() => {
          delFile(params).then((res) => {
            if (res.stat == 1) {
              _this.$message.success("删除成功");
              _this.getList();
            } else {
              _this.$message.error(res.msg);
            }
          })
        }).catch(action => {
          console.log('取消操作')
        });
      },
      // 退出登录
      onLogout() {
        this.$confirm('您是否要退出登录？', '温馨提示', {
          distinguishCancelAndClose: true,
          confirmButtonText: '确定',
          cancelButtonText: '取消'
        }).then(() => {
          window.location.href = './login.html'
        }).catch(action => {
          console.log('取消操作')
        });
      }
    },
    fillter: {},
  }

  ).$mount("#app")
</script>

</html>